package com.opencvjava.lessons.imgproc;

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.springframework.stereotype.Service;

import static com.opencvjava.support.util.CvUtils.imshow;
import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.core.Core.bitwise_not;
import static org.opencv.imgproc.Imgproc.ADAPTIVE_THRESH_MEAN_C;
import static org.opencv.imgproc.Imgproc.COLOR_BGR2GRAY;
import static org.opencv.imgproc.Imgproc.MORPH_HITMISS;
import static org.opencv.imgproc.Imgproc.MORPH_OPEN;
import static org.opencv.imgproc.Imgproc.MORPH_RECT;
import static org.opencv.imgproc.Imgproc.THRESH_BINARY;
import static org.opencv.imgproc.Imgproc.adaptiveThreshold;
import static org.opencv.imgproc.Imgproc.blur;
import static org.opencv.imgproc.Imgproc.cvtColor;
import static org.opencv.imgproc.Imgproc.dilate;
import static org.opencv.imgproc.Imgproc.erode;
import static org.opencv.imgproc.Imgproc.getStructuringElement;
import static org.opencv.imgproc.Imgproc.morphologyEx;

@Service
public class L7_MorphologicalLines {
    public void test() {
        Mat src = mat("morphology","music.png");
        // Check if image is loaded fine
        if (src.empty()) {
            throw new RuntimeException("读取图片失败");
        }
        // Show source image
        imshow("src", src);
        // Transform source image to gray if it is not already
        Mat gray = new Mat();
        if (src.channels() == 3) {
            cvtColor(src, gray, COLOR_BGR2GRAY);
        } else {
            gray = src;
        }
        // Show gray image
        imshow("gray", gray);
        // Apply adaptiveThreshold at the bitwise_not of gray
        Mat bw = new Mat();
        adaptiveThreshold(gray, bw, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
        imshow("binary0", bw);
        bitwise_not(gray, gray);
        adaptiveThreshold(gray, bw, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
        // Show binary image
        imshow("binary", bw);
        // Create the images that will use to extract the horizontal and vertical lines
        Mat horizontal = bw.clone();
        Mat vertical = bw.clone();
        // Specify size on horizontal axis
        int horizontal_size = horizontal.cols() / 30;
        // Create structure element for extracting horizontal lines through morphology operations
        Mat horizontalStructure = getStructuringElement(MORPH_RECT, new Size(horizontal_size, 1));
        // Apply morphology operations
//        erode(horizontal, horizontal, horizontalStructure);
//        dilate(horizontal, horizontal, horizontalStructure);
        morphologyEx(horizontal, horizontal, MORPH_OPEN, horizontalStructure);
        // Show extracted horizontal lines
        imshow("horizontal", horizontal);
        // Specify size on vertical axis
        int vertical_size = vertical.rows() / 30;
        // Create structure element for extracting vertical lines through morphology operations
        Mat verticalStructure = getStructuringElement(MORPH_RECT, new Size(1, vertical_size));
        // Apply morphology operations
//        erode(vertical, vertical, verticalStructure);
//        dilate(vertical, vertical, verticalStructure);
        morphologyEx(vertical, vertical, MORPH_OPEN, verticalStructure);
        // Show extracted vertical lines
        imshow("vertical", vertical);
        // Inverse vertical image
        bitwise_not(vertical, vertical);
        imshow("vertical_bit", vertical);
        // Extract edges and smooth image according to the logic
        // 1. extract edges
        // 2. dilate(edges)
        // 3. src.copyTo(smooth)
        // 4. blur smooth img
        // 5. smooth.copyTo(src, edges)
        // Step 1
        Mat edges = new Mat();
//        Imgproc.threshold(srcGray, dst, thresholdValue, MAX_BINARY_VALUE, thresholdType);
        adaptiveThreshold(vertical, edges, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, -2);
        imshow("edges", edges);
        // Step 2
        Mat kernel = Mat.ones(2, 2, CvType.CV_8UC1);
        dilate(edges, edges, kernel);
        imshow("dilate", edges);
        // Step 3
        Mat smooth = new Mat();
        vertical.copyTo(smooth);
        // Step 4
        blur(smooth, smooth, new Size(2, 2));
        // Step 5
        smooth.copyTo(vertical, edges);
        // Show final result
        imshow("smooth - final", vertical);
    }
}
